package com.qisu.socket.server.handlers;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import com.qisu.command.CommandDispatcher;
import com.qisu.socket.server.ChannelList;
import com.qisu.util.ByteArrayUtils;
import com.qisu.util.ExceptionMail;

import cn.hutool.core.date.DateUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;

/**
 *
 * @author alsan
 *
 */
@Component
@Configuration	
@Sharable
public class CommandHandler extends ChannelDuplexHandler {
	protected Log log = LogFactory.get();
	private boolean _cmdIsBigendian = true;

	// @formatter:off
	@Autowired private ExceptionMail _mailUtils;
	@Autowired private CommandDispatcher _dispatcher;
	@Autowired private ChannelList _channelList;

	@Value("${packet.command.pos}") private int _cmdPos;
	@Value("${packet.command.length}") private int _cmdLen;
	@Value("${packet.command.orderType}") private String _orderType;
	@Value("${project.name}") private String projectName;
	// @formatter:on

	private CustomChannelReader _custChannelReader;

	public CustomChannelReader getCustomChannelReader() {
		return _custChannelReader;
	}

	public void setCustomChannelReader(CustomChannelReader custChannelreader) {
		_custChannelReader = custChannelreader;
	}

	@PostConstruct
	public void init() {
		_cmdIsBigendian = _orderType.equalsIgnoreCase("big_endian");
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		_channelList.remove(ctx);
		ctx.close();
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		log.debug("    ####### Channel  Read  #######");
		
		if(null == _custChannelReader) {
			byte[] data = (byte[])msg;
			if(data.length > _cmdPos + _cmdLen) {
				int cmd = ByteArrayUtils.getInteger(data, _cmdPos, _cmdLen, _cmdIsBigendian);
				try {
					_dispatcher.dispatch(cmd).proceed(ctx, cmd, data);
				} catch(Exception e) {
					e.printStackTrace();

					String title = DateUtil.now() + "  错误码  : " + String.valueOf(cmd);
					StringWriter sw = new StringWriter();
					e.printStackTrace(new PrintWriter(sw));

					_mailUtils.send(title, projectName + "\n" + sw.toString());
					log.warn(sw.toString());
				}
			} else {
				log.warn("insufficient length to featch pile no");
			}
		} else {
			_custChannelReader.channelRead(ctx, msg);
		}
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}
}
